<?php


namespace app\logic\recharge;


use app\utils\Helper;
use coco\Exception;
use coco\Log;
use coco\Request;
use coco\Response;

class Flow extends Base implements Template
{

    public static function info(): array
    {
        return [
            'support_type' => 1,//支持类型
            'name' => '新驰',
            'cfg' => [
                //name 名称 required是否必填(默认必填) allow_edit种植期间是否允许修改(默认不允许)
                'mch_id' => ['name' => '商户号'],
                'key' => ['name' => '签名密钥', 'required' => false],
                'admin_url' => ['name' => '后台地址', 'allow_edit' => true],
                'api_url' => ['name' => '网关', 'allow_edit' => true],
                'ip_white_lists' => ['name' => '回调白名单', 'placeholder' => '多个逗号分割,不填表示不限制', 'allow_edit' => true, 'required' => false],  
                
                'productids' => ['name' => '产品编号', 'placeholder' => '多个逗号分割,格式yd50:30000005154,yd100:30000005155', 'allow_edit' => true, 'required' => false],                
            ],
        ];
    }
    /**
     * @param array $param
     * @return array|false
     * 返回false表示明确失败  订单会处理为失败状态
     * 其他表示成功或者未知 未知情况需要手动确认 或者定时查询
     * 时间间隔不一定 自行处理
     */
    public function submit(array $param)
    {
        $types = ['', 'yd', 'lt', 'dx'];
        try{
            $productids = array_column(array_map(function($v){
                list($i_p,$productid)=explode(':',$v);
                if(empty($productid))
                {
                    throw new Exception('`产品编号`配置出错');
                }
                $isp=substr($i_p,0,2);
                if(!in_array($isp,['yd','lt','dx']))
                {
                    throw new Exception('`产品编号`配置出错');
                }
                $price=substr($i_p,2);
                $key=$isp.'_'.$price;
                return compact('key','productid');
            },explode(',',$this->cfg['productids'])),'productid','key');
        }catch(\Exception $e)
        {
            $this->error = $e->getMessage();
            return false;
        }
        if(empty($productids[$types[$param['order']['ext2']].'_'.$param['price']]))
        {
            $this->error = '不支持的产品';
            return false;
        }

        $productid = $productids[$param['isp'].'_'.$param['price']];
        $isps = ['', 'CMCC', 'CUCC', 'CTCC'];
        $params = [
            "account" => $this->cfg['mch_id'],
            "consumerNo" => $param['trade_no'],
            'flowCode'=> $productid,
            "mobile" => $param['order']['uuid'],
            'ispCode' => $isps[$param['isp']],
            'cbkUrl' => $this->getNotifyUrl($param['platfrom_id']),
            "amount" => $param['price'],
            "timestamp" => time() . '000',
        ];

        $params["sign"] = self::sign($this->cfg['mch_id'], $this->cfg['key'], $params['timestamp']);
        $data = http_build_query($params);
        $url = $this->cfg['api_url'] . '/flow-receiver/api/recharge/feecbk';
        $log = [];
        $log['url'] = $url;
        $log['data'] = $data;
        if (false === $result = Helper::http_get($url . '?' . $data , 30, $data)) {
            $log['response'] = 'curl fail';
            return ['is_confirm' => 1, 'log' => $log];
        }
        $log['response'] = $result;
        $ret = json_decode($result, true);
        if (empty($ret)) {
            $log['decode'] = '服务器响应错误';
            return ['is_confirm' => 1, 'log' => $log];
        }
        $log['decode'] = json_encode($ret,JSON_UNESCAPED_UNICODE);
        if ($ret['status'] !== '001') {
            $this->error = $result;
            return false;
        }
        return ['log' => $log, 'out_trade_no' => $ret['orderNo']];
    }

    public function notify(Request $request, string $ip)
    {
        if (!empty($this->cfg['ip_white_lists'])) {
            $ip_white_lists = explode(',', $this->cfg['ip_white_lists']);
            if (!in_array($ip, $ip_white_lists)) {
                $this->error = '非法请求';
                return false;
            }
        }
        
        $param = $request->post();
        $sign = self::sign($this->cfg['mch_id'], $this->cfg['key'], $param['timestamp']);
        if ($param['sign'] != $sign) {
            $this->error = '签名错误';
            return false;
        }
        $status = $param["status"];
        $success = ['001',];
        // $fail = [9,];
        $ignore = ['002'];
        if (in_array($status, $success)) {
            $voucher = $param['voucherNo']??'';
            $ret = 'success';
        } elseif (in_array($status, $ignore)) {
            $ret = 'ignore';
        } else {
            $msg = '渠道充值失败';
            $ret = 'fail';
        }
        $out_trade_no = $param['consumerNo'];
        return ['ret' => $ret, 'msg' => $msg ?? '', 'trade_no' => $out_trade_no, 'voucher' => $voucher];
    }

    public function notifyResponse(): Response
    {
        $response = new Response(['type' => 'txt']);
        $response->setData(['txt' => 'SUCCESS']);
        return $response;
    }

    /**
     * @param array $param subimit 表内容
     * @param int $act 0 普通查询 1 成功查询 2确认查询
     * @return false|mixed|string
     */
    public function query(array $param, int $act = 0)
    {
        $params = [
            "account" => $this->cfg['mch_id'],
            "consumerNo" => $param['trade_no'],
            "timestamp" => time() . '000',
        ];
        $params["sign"] = self::sign($this->cfg['mch_id'], $this->cfg['key'], $params['timestamp']);
        $headers = array(
            "Content-Type:application/x-www-form-urlencoded;charset=utf-8",
        );
        $data = http_build_query($params);
        $url = $this->cfg['api_url'] . '/flow-receiver/api/query/feecbk';
        if (false === $result = Helper::http_get($url . '?' . $data , 30, $data)) {
            $log['response'] = 'curl fail';
            return false;
        }
        $log['response'] = $result;
        $ret = json_decode($result, true);
        if (empty($ret)) {
            $this->error = '服务器响应错误';
            return false;
        }
        $log['decode'] = json_encode($ret,JSON_UNESCAPED_UNICODE);
        
        if ($act === 1) {
            if ($ret['status'] == '001') {
                return ['ret' => 'success', 'voucher' => $ret['voucherNo'] ?? ''];
            } elseif ($ret['status'] === '002') {
                return ['ret' => 'other'];
            } else {
                return ['ret' => 'fail'];
            }
        } elseif ($act === 2) {
            return 'yes';
        }
        return $ret;
    }
    private static function sign($mch_id, $key, $timestamp)
    {
        $arr = [$mch_id, $key, $timestamp];
        sort($arr);
        $str = join('', $arr);
        return sha1($str);
    }
}